// 最简单的泛型
function identify<T> (arg: T) : T {
  return arg
}
let myIdentify: <T>(arg: T) => T = identify
// 或者不同的变量名字
let myIdentify2: <U>(arg: U) => U = identify
// 或者调用函数签名
let myIdentify3: {<T>(arg: T) : T} = identify
// 写一个泛型接口 将字面量表示方法大括号里面的拿出来，放到接口里
interface Gene {
  <T> (arg: T) : T
}
let myIdentify4: Gene = identify
// 接口接受参数的泛型
interface Gea<T> {
  (arg: T) : T
}


// 泛型的使用
let output = identify<string>('a') // 第一种使用方式

let output2 = identify('a') // 让编译器去推算类型

function logging<T> (arg: T) : T {
  // console.log(arg.length) //报错，因为 T 类型不一定会有 length 属性
  return arg
}

function logging2<T> (arg: T[]) : T[] {
  console.log(arg.length) //不报错，因为此时的 参数是一个 T 类型的数组，数组是有 length 属性的
  return arg
}

// 创建一个泛型类
class Ce<T> {
  zeroValue: T
  add: (x: T, y: T) => T
}

// 定义一个接口来描述约束条件
interface LengthWie {
  length: number
}
function log<T extends LengthWie> (arg: T) : T {
  console.log(arg.length)
  return arg
}